
package swdemo;

import swdemo.switcher;
import swdemo.udpcontrol;
import swdemo.log;

public class swgroup {
	static final int SW_CNT = 8;
	public switcher[] sw;
	udpcontrol udp;
	int  group;
	
	public swgroup(int gp, String ip, int pt) {
		sw = new switcher[SW_CNT];
		for (int i = 0; i < SW_CNT; i++) {
			sw[i] = new switcher();
			//sw[i].set(true);  test
			log.d("set sw %d\n",i);
		}
		udp = new udpcontrol(ip, pt);
		group = gp;

		update();
	}

	// 与板子通信，获取目前的状态，更新到sw中。
	public int update() {
		byte[] cmd = new byte[6];
		byte[] result;
		
		cmd[0] = (byte)0x7e;	// 固定前缀
		cmd[1] = 0x3;			// 报文size
		cmd[2] = 0x0;			// 节点编号，demo应该固定是0
		cmd[3] = (byte)0xf7;	// bank get 的命令，获取一组开关的状态
		cmd[4] = (byte)group;	// bank 编号
		cmd[5] = checksum(cmd,5); // 前边所有字节的异或

		udp.send(cmd);

		result = udp.recv();

		if (result.length != 6 ||
			result[0] != 0x7e  
			//checksum(result, 5) != result[5]
			) {
			// error
			log.d("checksum %x error, [%x]\n", result[5], checksum(result, 5));
			return -1;
		}

		readstatus(result[4]);	// status在第四字节
		return result[4] & 0xff;
	}

	// 将目前的sw中的状态组装成报文发送到板子。
	// 目前唯一的控制开关的方法。
	// 首先修改需要控制sw的status，然后调用该函数实际控制板子
	public int excute() {
		byte[] cmd = new byte[7];

		cmd[0] = (byte)0x7e;	// 固定前缀
		cmd[1] = 0x4;			// 报文size
		cmd[2] = 0x0;			// 节点编号，demo应该固定是0
		cmd[3] = (byte)0xf1;	// bank set 的命令，就是设置一组开关的状态
		cmd[4] = calstatus();	// 一组8个switcher的状态汇总到1byte
		cmd[5] = (byte)group;	// bank 编号
		cmd[6] = checksum(cmd,6); // 前边所有字节的异或

		udp.send(cmd);
		
		return cmd[4] & 0xff;	// 返回 8个 switcher 的状态
	}

	// 生成命令中需要的checksum byte
	private byte checksum(byte[] data, int len) {
		int check;

		check = data[0];
		for (int i = 1; i < len; i++) {
			check ^= data[i];
		}
		return (byte)check;
	}

	// 将一组8各开关的状态生成一个byte
	private byte calstatus() {
		
		int st = 0;
		for (int i = 0; i < SW_CNT; i++) {
			st |= sw[i].get()? 1 << i: 0;
		}

		return (byte)(st & 0xff);
	}

	// 将 byte 中的信息反映到 sw 对象中
	private void readstatus(byte st) {
		for (int i = 0; i < SW_CNT; i++) {
			if (((st >> i) & 1) == 0) {
				sw[i].set(false);
			} else {
				sw[i].set(true);
			}
		}
	}
}
